﻿using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using Kugar.Core.ExtMethod;
using Kugar.UI.Web.AdminLTE.Enums;
using Kugar.UI.Web.AdminLTE.Helpers;
using Kugar.UI.Web.AdminLTE.PageControls.Helpers.ButtonExtMethod;
using Microsoft.AspNetCore.Mvc.Rendering;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Kugar.UI.Web.AdminLTE.PageControls
{
    public class ButtonConfigBase:AdminLTEElementBase, ICommandElement
    {
        internal ButtonTypeEnum _type = ButtonTypeEnum.button;

        public ButtonConfigBase(ViewContext viewContext) : base(viewContext)
        {
            this.Type(ButtonTypeEnum.button);
        }
                                             
        internal string _title = "";
        internal ColorPaletteEnum _color = ColorPaletteEnum.@default;
        internal string _iconHtml = "";
        internal bool _hide = false;

        public ButtonCmdBase Command { set; get; }

        public string GetText => _title;

        public ColorPaletteEnum GetColor => _color;

        public string ReommentTag => _type == ButtonTypeEnum.link ? "a" : "button";
    }


    public interface ICommandElement
    {
        ButtonCmdBase Command { set; get; }
    }


    public abstract class ButtonCmdBase 
    {
        public virtual void RenderToButton(ButtonConfigBase btn)
        {
            RenderToElement(btn.Attributes);
        }

        public abstract void RenderToElement(TagAttrbute attr);

        public virtual string RenderToString()
        {
            var attr=new TagAttrbute();

            RenderToElement(attr);

            return attr.ToStringEx();
        }

        /// <summary>
        /// 根据当前配置,推荐使用的标签
        /// </summary>
        public virtual string ReommentTag => "button";
    }

    /// <summary>
    /// 弹出一个指定Url窗口
    /// </summary>
    public class ButtonCmd_ShowModal: ButtonCmdBase
    {
        private string _url = "";
        private string _onsuccess = "";
        private string _onClose = "";
        private bool _shadeClose = true;
        private bool _autoRefreshOnClose = false;
        private bool _autoRefreshWholePageOnClose = false;

        public ButtonCmd_ShowModal SetUrl(string url)
        {
            _url = url;

            return this;
        }

        public ButtonCmd_ShowModal SetOnSuccessCallback(string callback)
        {
            _onsuccess = callback;

            return this;
        }

        public ButtonCmd_ShowModal SetOnCloseModalCallback(string callback)
        {
            _onClose = callback;

            return this;
        }

        public ButtonCmd_ShowModal SetDisabledShadeClose(bool disabledShadeClose = true)
        {
            _shadeClose = !disabledShadeClose;
            return this;
        }

        public ButtonCmd_ShowModal SetOnRefreshPageOnClose(bool autoClose = true)
        {
            _autoRefreshOnClose = autoClose;

            return this;
        }

        public ButtonCmd_ShowModal SetOnRefreshWholePageOnClose(bool autoClose = true)
        {
            _autoRefreshWholePageOnClose = autoClose;

            return this;
        }

        public override void RenderToElement(TagAttrbute attr)
        {
            /*
             *    var defaultOpts = {
                        url: "",
                        data: {},
                        method:"get",
                        el:null,
                        onSuccessCallback: null,
                        onCloseCallback: null,
                        noRefreshEvent: false,
                        shadeOnClose: true,
                        refreshOnClose:false
                    }

             *
             */

            var s = $@"WebUIJS.ModalWindow({{url:'{_url}',onSuccessCallback:'{_onsuccess}', onCloseCallback:'{_onClose}', shadeOnClose:{_shadeClose.ToString().ToLower()} , refreshOnClose:{_autoRefreshOnClose.ToString().ToLower()} ,sender:$(this) }} );";

            //var script=$"WebUIJS.ModalByUrl('{_url}',null,{(string.IsNullOrWhiteSpace(_onsuccess) ? "null" : "'" + _onsuccess + "'")},{(string.IsNullOrWhiteSpace(_onClose)?"null":"'" + _onClose + "'")},'GET',false,{_shadeClose.ToString().ToLower()},{_autoRefreshOnClose.ToString().ToLower()})"; //,{{shadeClose:{_shadeClose.ToString().ToLower()}}}

            attr.Attributes.Add("onclick", s);
        }
    }

    public class ButtonCmd_Goto : ButtonCmdBase
    {
        private string _url = "";
        private LinkTargetType _linkTarget = LinkTargetType.Self;
        private bool _isOpenToBrowser = false;
        private bool _isAutoConcat = false;

        public ButtonCmd_Goto Url(string url)
        {
            _url = url;

            return this;
        }

        public ButtonCmd_Goto Target(LinkTargetType target)
        {
            _linkTarget = target;

            return this;
        }

        /// <summary>
        /// 是否自动拼接当前link最近的form的字段值,目前只 type=link的按钮有效 
        /// </summary>
        /// <param name="autoConcat"></param>
        /// <returns></returns>
        public ButtonCmd_Goto AutoConcatFormValue(bool autoConcat = true)
        {
            _isAutoConcat = autoConcat;

            return this;
        }

        public string GetUrl => _url;

        public LinkTargetType TaragetType => _linkTarget;

        /// <summary>
        /// 当使用iframe模式的时候,该属性用于设置打开连接时,直接打开新的浏览器页面,
        /// </summary>
        /// <param name="isOpenToBrowser"></param>
        /// <returns></returns>
        public ButtonCmd_Goto OpenToBrowser(bool isOpenToBrowser = false)
        {
            _isOpenToBrowser = isOpenToBrowser;

            return this;
        }


        public override void RenderToElement(TagAttrbute attr)
        {
            var target = Utility.LinkTargetToStr(_linkTarget);

            var btnType = attr.GetValue("type", "button");

            attr.Data("data-autoconcatform", _isAutoConcat.ToString().ToLower());

            if (btnType=="link")
            {
                attr.SetOrReplaceAttr("href", _url);
                attr.SetOrReplaceAttr("target", target);

                if (!_isAutoConcat)
                {
                    attr.SetOrReplaceAttr("webui-ignore", "webui-ignore");
                }
                
                
            }
            else
            {
                var script = $"WebUIJS.GoTo('{_url}',this,'{target}',{(!_isOpenToBrowser).ToStringEx().ToLower()})";

                attr.SetOrReplaceAttr("onclick", script);
            }
            
        }

        public override string ReommentTag => _isAutoConcat ? "a" : "button";
    }

    public class ButtonCmd_ClientClick : ButtonCmdBase
    {
        private string _script = "";
   
        public ButtonCmd_ClientClick SetOnClickScript(string script)
        {
            _script = script;

            return this;
        }

        public string Script => _script;
        
        public override void RenderToElement(TagAttrbute attr)
        {
            attr.SetOrReplaceAttr("onclick", _script);
        }
    }

    /// <summary>
    /// 异步执行一个功能命令
    /// </summary>
    public class ButtonCmd_ExecuteCmd : ButtonCmdBase
    {
        private JObject _args = null;
        private string _url = "";
        private string _cmdName = "";
        private string _tips = "";
        private bool _isAutoReresh = false;
        private string _afterCallabck = "";
        private bool _isAutoRefreshWholePage = false;

        public ButtonCmd_ExecuteCmd AutoRefreshPage(bool isAutoRefresh=true)
        {
            _isAutoReresh = isAutoRefresh;

            return this;
        }

        public ButtonCmd_ExecuteCmd AutoRefreshWholePage(bool isAutoRefresh = true)
        {
            _isAutoRefreshWholePage = isAutoRefresh;

            return this;
        }

        public ButtonCmd_ExecuteCmd SetTips(string tips)
        {
            _tips = tips;

            return this;
        }

        public ButtonCmd_ExecuteCmd SetArgs(JObject args)
        {
            _args = args;

            return this;
        }

        public ButtonCmd_ExecuteCmd SetArgs(object args)
        {
            _args = JObject.FromObject(args);

            return this;
        }

        public ButtonCmd_ExecuteCmd SetCmdUrl(string url)
        {
            _url = url;

            return this;
        }

        public ButtonCmd_ExecuteCmd SetMethodName(string cmdName)
        {
            _cmdName = cmdName;

            return this;
        }

        public ButtonCmd_ExecuteCmd SetOnSuccessCallback(string callback)
        {
            _afterCallabck = callback;

            return this;
        }

        public override void RenderToElement(TagAttrbute attr)
        {
            var onclick = "WebUIJS.AjaxToMethod(this);";

            attr.Data("data-args", WebUtility.HtmlEncode(_args.ToString(Formatting.None)));
            attr.Data("data-cmd", _cmdName);
            attr.Data("data-tips", _tips);
            attr.Data("data-url", _url);
            
            attr.Data("data-autorefresh", _isAutoReresh.ToStringEx());
            attr.Data("data-autorefreshwholepage", _isAutoRefreshWholePage.ToStringEx());

            attr.Data("data-aftersuccesscall", _afterCallabck.ToStringEx());
            attr.SetOrReplaceAttr("onclick", onclick);
        }
    }

    /// <summary>
    /// 弹出一个取数窗口
    /// </summary>
    public class ButtonCmd_ShowDataPicker : ButtonCmdBase
    {
        private string _url="";
        private string _selectedCallback = "";
        private string _showCallback = "";
        private JObject _fillConfig = null;
        private bool _storeInCache = false;
        private string _fillToTextFieldName = "";
        private string _fillToValueFieldName = "";
        private string _selectedAreaTableOrderbyKey = "";
        private int _selectedAreaTableOrderbyType = 0;
        private bool _selectedAreaTableOrderByNumeric = false;
        private bool _autoSelectWhenOnlyOne = false;
        private string _afterSelectedCallback = "";

        public ButtonCmd_ShowDataPicker SetUrl(string url)
        {
            _url = url;
            return this;
        }

        public ButtonCmd_ShowDataPicker OnSelectedCallback(string callback)
        {
            _selectedCallback = callback;

            return this;
        }

        public ButtonCmd_ShowDataPicker OnAfterSelectedCallback(string callback)
        {
            _afterSelectedCallback = callback;

            return this;
        }

        public ButtonCmd_ShowDataPicker OnShowCallback(string callback)
        {
            _showCallback = callback;

            return this;
        }

        public ButtonCmd_ShowDataPicker StoreInCache(bool isStoreInCache)
        {
            _storeInCache = isStoreInCache;
            return this;
        }

        public ButtonCmd_ShowDataPicker FillConfig(JObject fillConfig)
        {
            _fillConfig = fillConfig;

            return this;
        }


        /// <summary>
        /// 排序字段
        /// </summary>
        /// <param name="thCssName"></param>
        /// <param name="isAsc">是否为正序</param>
        /// <returns></returns>
        public ButtonCmd_ShowDataPicker SelectedAreaTableOrderbyKey(string thCssName, bool isAsc = true,bool orderByNumeric=false)
        {
            _selectedAreaTableOrderbyKey = thCssName;
            _selectedAreaTableOrderbyType = isAsc ? 0 : -1;
            _selectedAreaTableOrderByNumeric = orderByNumeric;

            return this;
        }

        public ButtonCmd_ShowDataPicker AutoSelectWhenOnlyOne(bool enable = true)
        {
            _autoSelectWhenOnlyOne = enable;

            return this;
        }

        /// <summary>
        /// 填充到文本框的字段的名称
        /// </summary>
        /// <param name="jsonFieldName">返回的数据中的字段名</param>
        /// <returns></returns>
        public ButtonCmd_ShowDataPicker FillToTitle(string jsonFieldName)
        {
            _fillToTextFieldName = jsonFieldName;

            return this;
        }

        /// <summary>
        /// 填充到文本框的字段的名称
        /// </summary>
        /// <param name="jsonFieldName">返回的数据中的字段名</param>
        /// <returns></returns>
        public ButtonCmd_ShowDataPicker FillToValue(string jsonFieldName)
        {
            _fillToValueFieldName = jsonFieldName;

            return this;
        }

        public override void RenderToElement(TagAttrbute attr)
        {
            if (_fillConfig!=null)
            {
                attr.Data("data-fillconfig", HttpUtility.HtmlEncode(_fillConfig.ToString(Formatting.None)));

                _selectedCallback = $"__dataPickerToConfig";
            }
            
            attr.Data("data-showdatapicker", _url);
            attr.Data("data-selectedcallback", _selectedCallback);
            attr.Data("data-afterSelectedCallback", _afterSelectedCallback);

            attr.Data("data-showcallback", _showCallback);
            attr.Data("data-filltotitle", _fillToTextFieldName);
            attr.Data("data-filltovalue", _fillToValueFieldName);
            attr.Data("data-orderby", _selectedAreaTableOrderbyKey.ToStringEx());
            attr.Data("data-orderbytype", _selectedAreaTableOrderbyType.ToStringEx());
            attr.Data("data-orderbynumeric", _selectedAreaTableOrderByNumeric.ToString().ToLower());

            attr.Data("data-option", HttpUtility.HtmlEncode(new JObject()
                                                       {
                                                           {"StoreInCache", _storeInCache},
                                                           {"AutoSelectWhenOnlyOne",_autoSelectWhenOnlyOne }
                                                       }.ToStringEx(Formatting.None)));


            attr.Class("datapickerbtn");

            //attr.SetOrReplaceAttr("onclick", $"WebUIJS.ShowDataPicker('{_url}','{_selectedCallback}','{_showCallback}',{{StoreInCache:{_storeInCache.ToString().ToLower()}}},$(this))");

        }
    }

    public class ButtcnCmd_AjaxUploadFile: ButtonCmdBase
    {
        private string _uploadUrl = "";
        private string _onSuccessCallback = "";
        private string _onFailCallback = "";
        private bool _autoRefreshPage = false;
        private string _name = "file";
        private string _accept = "*/*";
        private int _maxFileSize = 0;
        private string _tips = "";

        public ButtcnCmd_AjaxUploadFile SetUploadUrl(string uploadUrl)
        {
            _uploadUrl = uploadUrl;
            return this;
        }

        public ButtcnCmd_AjaxUploadFile SetOnSuccessCallback(string script)
        {
            _onSuccessCallback = script;
            return this;
        }

        public ButtcnCmd_AjaxUploadFile SetOnFailCallback(string script)
        {
            _onFailCallback = script;
            return this;
        }

        public ButtcnCmd_AjaxUploadFile SetAutoRefreshPage(bool autoRefreshPage = true)
        {
            _autoRefreshPage = autoRefreshPage;
            return this;
        }

        public ButtcnCmd_AjaxUploadFile SetName(string name)
        {
            _name = name;
            return this;
        }

        public ButtcnCmd_AjaxUploadFile SetAccept(string accept)
        {
            _accept = accept;
            return this;
        }

        public ButtcnCmd_AjaxUploadFile SetMaxFileSize(int maxFileSize)
        {
            _maxFileSize = maxFileSize;
            return this;
        }

        public ButtcnCmd_AjaxUploadFile SetTips(string tips)
        {
            _tips = tips;

            return this;
        }


        public override void RenderToElement(TagAttrbute attr)
        {
            attr.Data("data-onsuccesscallback", _onSuccessCallback)
                .Data("data-onfailcallback", _onFailCallback)
                .Data("data-autorefreshpage", _autoRefreshPage.ToString().ToLower())
                .Data("data-name", _name)
                .Data("data-accept", _accept)
                .Data("data-maxfilesize", _maxFileSize.ToStringEx())
                .Data("data-tips", _tips);
        
            var onclick = $"WebUIJS.ShowUploadFile('{_uploadUrl}',{{onSuccess:$(this).data('onsuccesscallback'),onError:$(this).data('onfailcallback'), sender:this, autoRefreshPage:$(this).data('autorefreshpage'),accept:$(this).data('accept'),fieldName:$(this).data('name') , maxFileSize:$(this).data('maxfilesize') ,tips:$(this).data('tips') }});";

            attr.SetOrReplaceAttr("onclick", onclick);
        }
    }

    public class ButtonCmd_ViewFile: ButtonCmdBase
    {
        private string _fileUrl = "";
        private string _mime = "";
        private string _title = "";
        private string _onLoadSuccesCallback="";
        private string _onCloseCallback = "";

        public ButtonCmd_ViewFile SetUrl(string url)
        {
            _fileUrl = url;
            return this;
        }

        public ButtonCmd_ViewFile SetMime(string mime)
        {
            _mime = mime;
            return this;
        }

        public ButtonCmd_ViewFile SetTitle(string title)
        {
            _title = title;

            return this;
        }

        /// <summary>
        /// 显示成功后,触发该回调,如果是pdf的,则为iframe加载完成后触发
        /// </summary>
        /// <param name="script"></param>
        /// <returns></returns>
        public ButtonCmd_ViewFile OnLoadSuccessCallback(string script)
        {
            _onLoadSuccesCallback = script;
            return this;
        }

        /// <summary>
        /// 关闭窗口后,回调
        /// </summary>
        /// <param name="script"></param>
        /// <returns></returns>
        public ButtonCmd_ViewFile OnCloseCallback(string script)
        {
            _onCloseCallback = script;

            return this;
        }

        public override void RenderToElement(TagAttrbute attr)
        {
            attr.Data("data-title", _title.ToStringEx());
            attr.Data("data-mime", _mime.ToStringEx());
            attr.Data("data-fileurl", _fileUrl.ToStringEx());
            attr.Data("data-onloadsuccesscallback", _onLoadSuccesCallback);
            attr.Data("data-onclosecallback",_onCloseCallback);


            attr.SetOrReplaceAttr("onclick",
                "WebUIJS.ShowFileViewer($(this).data('fileurl'),{title:$(this).data('title'),mime:$(this).data('mime'),onLoadedCallback:$(this).data('onloadsuccesscallback'),onCloseCallback:$(this).data('onclosecallback')");
        }
    }

    public class ButtonCmd_GeoPicker: ButtonCmdBase
    {
        private string _initAddress = "";
        private (string propertyName, string fillSelector)[] _fillTo = null;
        private string _onsuccessCallback = "";

        public ButtonCmd_GeoPicker InitAddress(decimal lng,decimal lat)
        {
            _initAddress = $"{{lng:{lng},lat:{lat}}}";

            return this;
        }

        public ButtonCmd_GeoPicker InitAddress(string address)
        {
            _initAddress = $"'{address}'";

            return this;
        }

        public ButtonCmd_GeoPicker InitAddressFromElement(string elementSelector)
        {
            _initAddress = $"$('{elementSelector}').val()";

            return this;
        }

        public ButtonCmd_GeoPicker FillTo(params (string fillSelector,string propertyName)[] fillConfig)
        {
            _fillTo = fillConfig;
            return this;    
        }

        public ButtonCmd_GeoPicker OnSuccessCallback(string script)
        {
            _onsuccessCallback = script;

            return this;
        }

        public override void RenderToElement(TagAttrbute attr)
        {
            var fillScript = "";

            if (_fillTo.HasData())
            {
                var s=_fillTo.Select(x => $"'{x.propertyName}':'{x.fillSelector}'").JoinToString(',');;
                fillScript = $" WebUIJS.FillDataToControl(data,{{ {s} }});";

            }

            var success = $"function(data){{debugger; {fillScript} \n {_onsuccessCallback}; }}";

            attr.SetOrReplaceAttr("onclick", $"WebUIJS.ShowLocationSelector( {success} ,{_initAddress})");
        }
    }
}
